package com.matrix.app.flux.project.stage.service.impl;

import com.matrix.app.common.enums.StageStatus;
import com.matrix.app.flux.project.stage.data.StageDto;
import com.matrix.app.flux.project.stage.data.StagePo;
import com.matrix.app.flux.project.stage.data.StageVO;
import com.matrix.app.flux.project.stage.repository.StageRepository;
import com.matrix.app.flux.project.stage.service.StageService;
import com.matrix.framework.core.common.global.IOptionService;
import com.matrix.framework.core.common.global.Options;
import com.matrix.framework.lowcode.enums.EventLocation;
import com.matrix.framework.lowcode.eventintf.annotation.ExtendEvent;
import com.matrix.framework.lowcode.eventintf.event.AfterQueryEvent;
import com.matrix.framework.lowcode.eventintf.event.BeforeEditEvent;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.util.List;
import java.util.Map;

/**
 * 项目阶段服务实现
 *
 * Copyright © 海平面工作室 版权所有
 *
 * @Author: Leo
 * @Create: 2025/06/02 10:00
 * @Since 1.2
 */
@Service
public class StageServiceImpl implements StageService, IOptionService, AfterQueryEvent, BeforeEditEvent {

    private final StageRepository repository;

    @Override
    public Mono<List<Options>> getOptions(Map<String, String> filter) {
        return repository.findAll()
                .collectList()
                .map(stages -> stages.stream()
                        .map(p -> new Options(p.getName(), p.getId() + ""))
                        .toList());
    }

    /**
     * 构造函数注入阶段仓库
     * @param repository 阶段仓库
     */
    public StageServiceImpl(StageRepository repository) {
        this.repository = repository;
    }

    /**
     * 新增阶段
     * @param stage 阶段信息
     * @return 新增后的阶段
     */
    @Override
    public Mono<StagePo> save(StagePo stage) {
        return repository.save(stage);
    }

    /**
     * 根据ID删除阶段
     * @param id 阶段ID
     * @return 被删除的阶段信息
     */
    @Override
    public Mono<StagePo> deleteById(Long id) {
        return repository.findById(id)
                .flatMap(stage -> repository.deleteById(id).thenReturn(stage));
    }

    /**
     * 根据ID查询阶段
     * @param id 阶段ID
     * @return 阶段信息
     */
    @Override
    public Mono<StagePo> findById(Long id) {
        return repository.findById(id);
    }

    /**
     * 分页查询项目阶段
     * @param dto 查询条件
     * @return 阶段VO列表
     */
    @Override
    public Mono<StageDto> findStages(StageDto dto) {
        String searchKey = dto != null && dto.getSearchKey() != null && !dto.getSearchKey().isEmpty() 
                ? dto.getSearchKey() : null;
        int pageNo = dto != null && dto.getPage() > 0 ? dto.getPage() : 1;
        int size = dto != null && dto.getPageSize() > 0 ? dto.getPageSize() : 10;
        
        PageRequest pageable = PageRequest.of(pageNo - 1, size);
        
        return repository.findByConditions(searchKey, pageable)
                .map(stage -> {
                    StageVO vo = new StageVO();
                    vo.setId(stage.getId());
                    vo.setName(stage.getName());
                    vo.setMemo(stage.getMemo());
                    if (stage.getStatus() != null) {
                        try {
                            vo.setStatus(StageStatus.valueOf(stage.getStatus()).getDescription());
                        } catch (IllegalArgumentException e) {
                            vo.setStatus(stage.getStatus());
                        }
                    } else {
                        vo.setStatus("");
                    }
                    return vo;
                })
                .collectList()
                .zipWith(repository.countByConditions(searchKey))
                .map(tuple -> {
                    StageDto result = dto != null ? dto : new StageDto();
                    result.setItems(tuple.getT1());
                    result.setTotal(tuple.getT2());
                    return result;
                });
    }

    @Override
    @ExtendEvent(tableName = "project_work_item", eventLocation = EventLocation.AFTER_QUERY, description = "项目分解列表查询后事件, 将阶段id转换为阶段名称供表格显示")
    public Mono<Map<String, Object>> doAfterQuery(Map<String, Object> result) {
        return Mono.just(result)
                .publishOn(Schedulers.boundedElastic())
                .flatMap(d -> {
                    if (d.containsKey("items")) {
                        List<Map<String, Object>> items = (List<Map<String, Object>>) d.get("items");
                        for (Map<String, Object> item : items) {
                            if (item.containsKey("stage_id")) {
                                Long stageId = (Long) item.remove("stage_id");
                                if (stageId != null) {
                                    Mono<StagePo> stage = repository.findById(stageId);
                                    // 取出Mono中的值并赋值给stage_id
                                    StagePo stagePo = stage.block();
                                    item.put("stage_id", stagePo != null ? stagePo.getName() : "");
                                }
                            }
                        }
                    }
                    return Mono.just(d);
                });
    }

    @Override
    @ExtendEvent(tableName = "project_work_item", eventLocation = EventLocation.BEFORE_EDIT, description = "项目分解列表编辑前事件, 将阶段名称转换为阶段id")
    public Mono<Map<String, Object>> doBeforeEdit(Map<String, Object> data) {
        return Mono.just(data)
                .publishOn(Schedulers.boundedElastic())
                .map(d -> {
                    Object stageId = data.remove("stage_id");
                    if (stageId != null) {
                        Mono<StagePo> po = repository.findById((Long) stageId);
                        StagePo stagePo = po.block();
                        if (stagePo != null) {
                            data.put("stage_id", stagePo.getName());
                        }
                    }
                    return d;
                });

    }
}